package com.hyhy.hycloud.uaa.security.provider;

import com.hyhy.hycloud.commons.util.text.TextValidator;
import com.hyhy.hycloud.uaa.security.PasswordType;
import com.hyhy.hycloud.uaa.security.SecurityUser;
import com.hyhy.hycloud.uaa.security.exception.BadAuthVerificationCodeException;
import com.hyhy.hycloud.uaa.service.AppIdConfigFinder;
import com.hyhy.hycloud.uaa.service.SmsVerificationCodeByMobileFinder;
import com.hyhy.hycloud.uaa.service.UserDetailsByMobileFinder;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.util.Assert;

import java.util.List;

import static com.hyhy.hycloud.uaa.Constants.LOGIN_BIZ_CODE;

/**
 * 手机号密码认证提供者
 *
 * @author Xuegui Yuan
 * @date 2018-09-19
 */
@Builder
public class MobilePasswordAuthenticationProvider extends AbstractAuthenticationProvider {

    private UserDetailsByMobileFinder userDetailsByMobileFinder;

    private PasswordEncoder passwordEncoder;

    private AppIdConfigFinder appIdConfigFinder;

    private SmsVerificationCodeByMobileFinder smsVerificationCodeByMobileFinder;

    @Override
    boolean isSupportAuthRequest(PasswordType passwordType, String appId, String principal) {
        List<String> supportedAppIdList = appIdConfigFinder.supportMobilePasswordList();
        return (PasswordType.PASSWORD == passwordType || PasswordType.UNDEFINED == passwordType)
                && (supportedAppIdList != null && supportedAppIdList.contains(appId))
                && TextValidator.isMobileSimple(principal);
    }

    @Override
    UserDetails authenticationCredentials(String appId,
                                          String principal, String credentials) {
        UserDetails userDetails = userDetailsByMobileFinder.findUserDetailsByMobile(appId, principal);
        if (!passwordEncoder.matches(credentials, userDetails.getPassword())) {
            throw new BadCredentialsException("Invalid user credentials");
        }
        return userDetails;
    }

    @Override
    public void authenticateTfaCode(String appId, SecurityUser securityUser, String tfaCode) {
        Assert.hasText(tfaCode, "'tfaCode' must has text");
        String code = smsVerificationCodeByMobileFinder.findSmsVerificationCode(LOGIN_BIZ_CODE, securityUser.getMobile());
        if (!tfaCode.equals(code)) {
            throw new BadAuthVerificationCodeException("Invalid SMS verification Code");
        }
    }
}
